# 在Python中实现牛顿迭代法，通常用于求解方程的根。
# 这里给出一个通用的牛顿迭代法函数示例：
import sympy as sp
import numpy as np


def newton_raphson(f, df, x0, epsilon=1e-6, max_iter=1000):
    """
    牛顿-拉弗森迭代法（Newton-Raphson method）

    参数:
    f : sympy函数对象，代表需要求根的函数
    df : sympy函数对象，代表f(x)关于x的导数
    x0 : 初始猜测值
    epsilon : 迭代停止条件的误差阈值
    max_iter : 最大迭代次数

    返回:
    近似解
    """

    # 将初始值转换为浮点数以便进行数值计算
    x = float(sp.N(x0))
    i = 0

    for _ in range(max_iter):
        i += 1

        # 计算当前值处的函数值和导数值，并将其转换为浮点数进行比较
        fx = float(sp.lambdify('x', f)(x))
        dfx = float(sp.lambdify('x', df)(x))

        # 如果导数接近于零，则停止迭代并返回当前解
        if abs(dfx) < epsilon:
            print("导数接近于零，迭代终止")
            break

        # 确保导数不为零后再执行下一步迭代
        if dfx != 0:
            next_x = x - fx / dfx
        else:
            print("在迭代过程中遇到导数为零的情况，跳过此次迭代")
            continue

        # 检查是否达到收敛条件
        if abs(next_x - x) < epsilon:
            print(f"在迭代 {i} 次后达到收敛条件")
            return next_x

        # 更新猜测值
        x = next_x

    print("达到最大迭代次数，未收敛")
    return x


# 示例：求解方程 x^3 + sin(x) - 1 = 0 的根，初始猜测值为 x0 = 0.5
x = sp.symbols('x')
f = x ** 3 + sp.sin(x) - 1
df = sp.diff(f, x)

root = newton_raphson(f, df, 0.5)
print(f"找到的根是: {root}")
